package com.hzlx.web;

import com.hzlx.dto.MenuDto;
import com.hzlx.dto.ResultDto;
import com.hzlx.service.PermissionService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import java.util.List;

@RestController
@Slf4j
public class PermissionController {
    @Resource
    PermissionService permissionService;
    @GetMapping("/api/menus")
    public Mono<ResultDto<List<MenuDto>>> menus(){
        return ReactiveSecurityContextHolder.getContext()
                .flatMap(ctx -> {
                    Authentication auth = ctx.getAuthentication();
                    if (auth == null) {
                        log.warn("认证对象为空，拒绝访问。");
                        return Mono.error(new RuntimeException("非法访问: 认证信息缺失"));
                    }
                    log.info("欢迎{}登录", auth.getPrincipal());
                    String principal = auth.getPrincipal().toString();
                    // permissionService.findMenus 返回 List<MenuDto>
                    // Mono.fromCallable 将阻塞的 findMenus 包装成 Mono
                    return Mono.fromCallable(() -> permissionService.findMenus(principal))
                            // 使用 map 将 List<MenuDto> 转换为 ResultDto<List<MenuDto>>
                            .map(menus -> ResultDto.<List<MenuDto>>builder()
                                    .code("ok")
                                    .data(menus)
                                    .build())
                            // 如果 findMenus 是阻塞操作，需要调度到合适的线程
                            .subscribeOn(Schedulers.boundedElastic());
                })
                // 统一处理所有可能发生的运行时异常
                .onErrorResume(RuntimeException.class, e -> {
                    log.error("获取菜单过程中发生错误: {}", e.getMessage(), e);
                    return Mono.just(ResultDto.<List<MenuDto>>builder()
                            .code("error")
                            .message(e.getMessage())
                            .build());
                })
                // 如果 ReactiveSecurityContextHolder.getContext() 结果为空（没有安全上下文）
                .switchIfEmpty(Mono.just(ResultDto.<List<MenuDto>>builder()
                        .code("error")
                        .message("未找到安全上下文")
                        .build()));
    }
}
